using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using MySql.Data.MySqlClient;
using System.Data;

namespace RBAC.Interstructrue.Base
{
    public class DbConnectionFactory : IDbConnectionFactory
    {
        private readonly string _connectionString;
        private readonly ILogger<DbConnectionFactory> _logger;

        public DbConnectionFactory(IConfiguration configuration, ILogger<DbConnectionFactory> logger)
        {
            _connectionString = configuration.GetConnectionString("MySQL") ?? 
                throw new InvalidOperationException("MySQL connection string is not configured");
            _logger = logger;
        }

        public IDbConnection CreateConnection()
        {
            try
            {
                var connection = new MySqlConnection(_connectionString);
                
                // 设置连接属性（只能设置可写的属性）
                connection.StateChange += (sender, e) =>
                {
                    if (e.OriginalState == ConnectionState.Closed && e.CurrentState == ConnectionState.Open)
                    {
                        _logger.LogInformation("MySQL connection opened successfully");
                    }
                    else if (e.OriginalState == ConnectionState.Open && e.CurrentState == ConnectionState.Closed)
                    {
                        _logger.LogInformation("MySQL connection closed");
                    }
                };

                // 自动打开连接
                connection.Open();
                
                // 验证连接是否真正打开
                if (connection.State != ConnectionState.Open)
                {
                    _logger.LogWarning("Connection state is not Open after Open() call, attempting to open again...");
                    connection.Open();
                }
                
                // 测试连接是否可用
                using (var testCommand = connection.CreateCommand())
                {
                    testCommand.CommandText = "SELECT 1";
                    testCommand.CommandTimeout = 30; // 30秒命令超时
                    testCommand.ExecuteScalar();
                }
                
                _logger.LogInformation("MySQL connection created and opened successfully, State: {State}", connection.State);
                return connection;
            }
            catch (MySql.Data.MySqlClient.MySqlException ex)
            {
                _logger.LogError(ex, "MySQL specific error occurred while creating connection: {ErrorCode} - {Message}", ex.Number, ex.Message);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Unexpected error occurred while creating MySQL connection: {Message}", ex.Message);
                throw;
            }
        }

        public IDbConnection CreateConnectionWithRetry(int maxRetries = 3, int delayMs = 2000)
        {
            for (int i = 0; i < maxRetries; i++)
            {
                try
                {
                    var connection = CreateConnection();
                    
                    // 验证连接状态
                    if (connection.State == ConnectionState.Open)
                    {
                        _logger.LogInformation("MySQL connection created successfully on attempt {Attempt}", i + 1);
                        return connection;
                    }
                    else
                    {
                        _logger.LogWarning("Connection created but state is {State} on attempt {Attempt}", connection.State, i + 1);
                        connection.Dispose();
                    }
                }
                catch (MySql.Data.MySqlClient.MySqlException ex) when (i < maxRetries - 1)
                {
                    _logger.LogWarning(ex, "MySQL connection attempt {Attempt} failed, retrying in {Delay}ms...", i + 1, delayMs);
                    Thread.Sleep(delayMs);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "MySQL connection failed after {Attempts} attempts", i + 1);
                    throw;
                }
            }
            
            throw new InvalidOperationException($"Failed to create MySQL connection after {maxRetries} attempts");
        }
    }
} 